package blog.juejin.socket.client;

import com.alibaba.fastjson.JSONObject;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * author : yeswater
 * date : 2024/8/8
 */

public class Client {
    
    private static Socket socket;
    
    public static boolean socketStatus = false; // 是否连接成功
    
    public static void main(String[] args) {
        while (!socketStatus) {
            try {
                connect();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    private static void connect() {
        try {
            socket = new Socket("localhost", 6301);
            socketStatus = true;
            ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
            new Thread(new ClientReader(socket, inputStream)).start();
            new Thread(new ClientWriter(socket, outputStream)).start();
            new Thread(new ClientHeart(socket, outputStream)).start();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    public static void reconnect() {
        while (!socketStatus) {
            System.out.println("正在尝试重新连接...");
            connect();
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

class ClientReader implements Runnable {
    
    private ObjectInputStream objectInputStream;
    
    public ClientReader(Socket socket, ObjectInputStream objectInputStream) {
        this.objectInputStream = objectInputStream;
    }
    
    @Override
    public void run() {
        while (true) {
            try {
                System.out.println(objectInputStream.readObject());
            } catch (IOException | ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

class ClientWriter implements Runnable {
    
    private Socket socket;
    
    private ObjectOutputStream objectOutputStream;
    
    public ClientWriter(Socket socket, ObjectOutputStream objectOutputStream) {
        this.socket = socket;
        this.objectOutputStream = objectOutputStream;
    }
    
    @Override
    public void run() {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            try {
                System.out.println(socket.getLocalPort() + "客户端 请输入:");
                String str = scanner.nextLine();
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("type", "msg");
                jsonObject.put("content", str);
                objectOutputStream.writeObject(jsonObject);
                objectOutputStream.flush(); // flush 把数据从缓存 buffer刷到流中
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

class ClientHeart implements Runnable {
    
    Socket socket;
    
    ObjectOutputStream objectOutputStream;
    
    public ClientHeart(Socket socket, ObjectOutputStream objectOutputStream) {
        this.socket = socket;
        this.objectOutputStream = objectOutputStream;
    }
    
    @Override
    public void run() {
        try {
            while (true) {
                Thread.sleep(5000);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("type", "heart");
                jsonObject.put("content", "===心跳💓===");
                
                objectOutputStream.writeObject(jsonObject);
                objectOutputStream.flush();
            }
        } catch (Exception e) {
            // throw new RuntimeException(e);
            e.printStackTrace();
            try {
                // 连接异常断开后的操作
                socket.close();
                Client.socketStatus = false;
                Client.reconnect();
            } catch (Exception ex) {
                e.printStackTrace();
            }
            
        }
    }
}
